/* ---------------------------------------------------------------------
 *
 * -- Privacy-preserving Sharing of Sensitive information Toolkit (PSST)
 *    (C) Copyright 2010 All Rights Reserved
 *
 * -- PSST routines -- Version 1.0.1 -- April, 2010
 * Bcckls corresponds to protocol JL09 in the paper
 *
 * Author         : Yanbin Lu
 * Security and Privacy Research Outfit (SPROUT),
 * University of California, Irvine
 *
 * -- Bug report: send email to yanbinl@uci.edu
 * ---------------------------------------------------------------------
 *
 * -- Copyright notice and Licensing terms:
 *
 *  Redistribution  and  use in  source and binary forms, with or without
 *  modification, are  permitted provided  that the following  conditions
 *  are met:
 *
 * 1. Redistributions  of  source  code  must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce  the above copyright
 *    notice,  this list of conditions, and the  following disclaimer in
 *    the documentation and/or other materials provided with the distri-
 *    bution.
 * 3. The name of the University,  the SPROUT group,  or the names of its
 *    authors  may not be used to endorse or promote products deri-
 *    ved from this software without specific written permission.
 *
 * -- Disclaimer:
 *
 * THIS  SOFTWARE  IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,  INCLUDING,  BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE UNIVERSITY
 * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,  INDIRECT, INCIDENTAL, SPE-
 * CIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
 * TO,  PROCUREMENT  OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEO-
 * RY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT  (IN-
 * CLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */

#include "bcckls_psi_server.h"
#include "crypto_tool.h"
#include "basic_tool.h"
#include "mpz_tool.h"

Bcckls_Server::Bcckls_Server()
{
  m_k = Memreuse::New();
  m_e = Memreuse::New();
  m_g = Memreuse::New();
  m_gtoa = Memreuse::New();
  m_h = Memreuse::New();
  m_n = Memreuse::New();
  m_n2 = Memreuse::New();
  m_q = Memreuse::New();
  m_sk = Memreuse::New();
  m_pk = Memreuse::New();
  m_Cku = Memreuse::New();
  m_Cke = Memreuse::New();
  m_minusA = Memreuse::New();
  m_pp = Memreuse::New();
  m_qq = Memreuse::New();
  m_gg = Memreuse::New();
}

void Bcckls_Server::LoadData()
{
  m_set.clear();
  m_rawset.clear();

  ifstream infile(m_strInputFile.c_str());
  if (!infile)
	{
	  cerr<<"open "<<m_strInputFile<<" error"<<endl;
	  return;
	}
  string element;
  while (getline(infile, element) && infile.good())
	{
	  m_rawset.push_back(element);
	  mpz_t * e = Memreuse::New();
	  string hs = CryptoTool::Hash(element);
	  MpzTool::Mpz_from_string(e, hs);
	  mpz_mod(*e, *e, *m_qq);
	  m_set.push_back(e);
	}
}

void Bcckls_Server::Setup(int nbits)
{
  stringstream keyfile;
  keyfile<<"rsa."<<nbits<<".pub";
  BasicTool::Load_RSA_Pub_Key(keyfile.str(), m_e, m_n, m_g, m_q);
  mpz_add_ui(*m_h, *m_n, 1);
  mpz_mul(*m_n2, *m_n, *m_n);

  mpz_t * mpz_2n = Memreuse::New();
  rn.Get_Z_Range(m_g, m_n2);
  mpz_mul_ui(*mpz_2n, *m_n, 2);
  mpz_powm(*m_g, *m_g, *mpz_2n, *m_n2);
  Memreuse::Delete(mpz_2n);

  rn.Get_Z_Range(m_sk, m_q);
  mpz_powm(*m_pk, *m_g, *m_sk, *m_n2);

  BasicTool::Load_DSA_Pub_Key(m_pp, m_qq, m_gg, NULL, "dsa.1024.pub"); // m_qq 160bits

  rn.Get_Z_Range(m_k, m_qq);
  LoadData();
  rn.Initialize(nbits);
}

void Bcckls_Server::Initialize(int nbits)
{
  mpz_t * f = Memreuse::New();
  for (size_t i = 0; i < m_set.size(); i++)
    {
      mpz_add(*f, *m_k, *m_set[i]);
      mpz_mod(*f, *f, *m_qq);
      mpz_invert(*f, *f, *m_qq); 
      mpz_powm(*f, *m_gg, *f, *m_pp); // double check modulus
      m_vecFS.push_back(CryptoTool::Hash(f));
    }
}

void Bcckls_Server::PublishData(vector<string>& output)
{
  CryptoTool::CSEnc(m_Cku, m_Cke, m_k, m_g, m_h, m_pk, m_q, m_n, m_n2);
  output.push_back(MpzTool::Mpz_to_string(m_pk));
  output.push_back(MpzTool::Mpz_to_string(m_Cku));
  output.push_back(MpzTool::Mpz_to_string(m_Cke));
  output.insert(output.end(), m_vecFS.begin(), m_vecFS.end());
}

int Bcckls_Server::OnRequest1(const vector<string>& input)
{
  mpz_t * e2u = Memreuse::New();
  mpz_t * e2e = Memreuse::New();
  mpz_t * x = Memreuse::New();
  for (size_t i = 0; i < input.size(); i += 2)
	{
	  MpzTool::Mpz_from_string(e2u, input[i]);
	  MpzTool::Mpz_from_string(e2e, input[i+1]);
	  CryptoTool::CSDec(x, e2u, e2e, m_sk, m_n, m_n2);
	  mpz_mod(*x, *x, *m_qq);


	  mpz_invert(*x, *x, *m_qq);
	  mpz_powm(*x, *m_gg, *x, *m_pp);
	  m_output.push_back(MpzTool::Mpz_to_string(x));
	}
  Memreuse::Delete(e2u);
  Memreuse::Delete(e2e);
  Memreuse::Delete(x);
  return 0;
}
